﻿
namespace BLPicker.Factory
{
    using System.Diagnostics;
    using System.Diagnostics.Contracts;

    /// <summary>
    /// Base class for business layer proxy.
    /// </summary>
    /// <typeparam name="TBusinessLayer">Type of business layer.</typeparam>
    public class BusinessLayerFactoryProxy<TBusinessLayer> : IBusinessLayerFactory<TBusinessLayer>
    {

        private const uint DefaultStackLevel = 1;

        /// <summary>
        /// Factory for getting instance of business layer from dependency container.
        /// </summary>
        private readonly IBusinessLayerFactory<TBusinessLayer> _factory;

        /// <summary>
        /// The level of stack for getting name of calling method.
        /// </summary>
        private readonly uint _stackLevel;

        /// <summary>
        /// ctor.
        /// </summary>
        /// <param name="businessLayerFactory">Factory for getting instance of business layer from dependency container.</param>
        public BusinessLayerFactoryProxy(IBusinessLayerFactory<TBusinessLayer> businessLayerFactory)
            : this(businessLayerFactory, DefaultStackLevel)
        {
            Contract.Requires(businessLayerFactory != null);

            _factory = businessLayerFactory;
        }

        /// <summary>
        /// ctor.
        /// </summary>
        /// <param name="businessLayerFactory">Factory for getting instance of business layer from dependency container.</param>
        /// <param name="stackLevel">The level of stack for getting name of calling method.</param>
        public BusinessLayerFactoryProxy(IBusinessLayerFactory<TBusinessLayer> businessLayerFactory, uint stackLevel)
        {
            Contract.Requires(businessLayerFactory != null);
            Contract.Requires(stackLevel > 0);

            _factory = businessLayerFactory;
            _stackLevel = stackLevel;
        }

        /// <summary>
        /// Gets method-named instance of business layer.
        /// </summary>
        /// <returns>The method-named instance of business layer.</returns>
        public TBusinessLayer GetBusinessLayer()
        {
            return GetBusinessLayer(new StackTrace().GetFrame((int)_stackLevel).GetMethod().Name);
        }

        /// <summary>
        /// Gets named instance of business layer or unnamed if named is not found.
        /// </summary>
        /// <returns>The named instance of business layer.</returns>
        public TBusinessLayer GetBusinessLayer(string name)
        {
            TBusinessLayer businessLayer = _factory.GetBusinessLayer(name);

            if (businessLayer == null)
                businessLayer = _factory.GetBusinessLayer();

            return businessLayer;
        }

    }

}
